#pragma once

#include <Socket.h>
#include <AsyncLogger.h>
#include <Buffer.h>
#include <CallbackDefine.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <cstring>
#include <memory>
#include <iostream>
#include <thread>

class TcpServer;

class TcpConnection : public std::enable_shared_from_this<TcpConnection>
{
public:
    TcpConnection(event_base* base, Socket* socket, bool setThreadSafe = true);
    bufferevent *getBufferevent() { return bev_; }
    event_base* getBase() { return base_; }
    std::string name() { return name_; }

    void setTimeout(const struct timeval& timeout);

    void cancelTimeout();

    void setMessageCallback(MessageCallback cb) { messageCallback_ = cb; }

    void setWriteCompleteCallback(WriteCompleteCallback cb) { writeCompleteCallback_ = cb; }

    void setCloseCallback(CloseConnectionCallback cb) { closeCallback_ = cb; }

    // 该函数的封装不完整
    void send(const char* msg,int len);

    void shutdown();

    void close();

    ~TcpConnection();

    std::string localAddress() { return localIp_; };
    uint16_t loaclPort() const { return localPort_; }
    std::string peerAddress() { return peerIp_; }
    uint16_t peerPort() const { return peerPort_; }

    void enableRead();

    void enableWrite();

    void disableRead();

    void disableWrite();

    std::string enableEventMsg();

private:
    void handleRead(struct bufferevent *bev, void *ctx);

    void handleWrite(struct bufferevent *bev, void *ctx);

    void handleEvent(struct bufferevent *bev, short what, void *ctx);

    void handleError();

    void handleClose();

private:
    bool isShutdown_;
    bool isWriting_;
    event_base *base_;
    bufferevent *bev_;
    std::string name_;
    std::string localIp_;
    uint16_t localPort_;
    std::string peerIp_;
    uint16_t peerPort_;
    std::unique_ptr<Socket> sock_;
    struct timeval timeoutVal_;

    Buffer inBuffer_;
    Buffer outBuffer_;
    // note: 自定义消息处理函数，由外界传入，所以可以自定义如何处理消息
    CloseConnectionCallback closeCallback_;
    MessageCallback messageCallback_;
    WriteCompleteCallback writeCompleteCallback_;
};